package com.lmx.persistence.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.lmx.common.constants.CommonConstants;
import com.lmx.common.context.ActionContextHolder;
import com.lmx.common.util.CommonUtil;
import com.lmx.repoDomain.exception.BusinessException;
import com.lmx.repoDomain.tmodel.Customer;
import com.lmx.repoDomain.tmodel.CustomerBill;
import com.lmx.repoDomain.tmodel.CustomerBusinessFlow;
import com.lmx.repoDomain.tmodel.CustomerDayBill;
import com.lmx.repoDomain.tmodel.CustomerLeave;
import com.lmx.repoDomain.tmodel.CustomerServerChange;
import com.lmx.repoDomain.tmodel.CustomerServiceBill;
import com.lmx.repoDomain.tmodel.Dicttype;
import com.lmx.repoDomain.tmodel.Employee;
import com.lmx.repoDomain.tmodel.NursingLevel;
import com.lmx.repoDomain.tmodel.NursingProject;
import com.lmx.repoDomain.tmodel.RechargeRecord;
import com.lmx.repoDomain.tmodel.SettlementBill;
import com.lmx.repoDomain.tmodel.TradeAccount;
import com.lmx.repoDomain.tmodel.TradeDetail;
/**
 * 
 * 
 * @author huibati
 * @version 1.00
 */
@Service
@Scope("prototype")
public class AccountService<T> {

	private Log logger = LogFactory.getLog(this.getClass());

	@PersistenceContext
	private EntityManager em;

	@Autowired   
	protected GenericService dslJpaService;

	@Autowired
	protected WorkPlaceService workPlaceService;

	@Autowired
	protected NursingService nursingService;
	
	@Autowired
	protected DicttypeService dicttypeService;

	@Autowired
	private CommonService commonService;
	
	@Autowired
	private CustomerLeaveService customerLeaveService;
	
	@Resource(name = "jdbcTemplate")
	private JdbcTemplate jdbcTemplate;

	protected JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}
	
	// 获取充值记录
	public RechargeRecord getRechargeRecordById(Long orgId) {
		RechargeRecord cb = (RechargeRecord) this.em.createQuery("select c from RechargeRecord c where c.id = ?1  ")
				.setParameter(1, orgId).getSingleResult();
		return cb;
	}


	// 获取账户
	public TradeAccount getTradeAccountByOrg(Long orgId) {
		TradeAccount cb = (TradeAccount) this.em.createQuery("select c from TradeAccount c where c.org.id = ?1 and c.delStatus != ?2 ")
				.setParameter(1, orgId).setParameter(2, (short)1).getSingleResult();
		return cb;
	}
	
	/**
	 * 根据用户和账户类型获取账户余额
	 * @param customerId
	 * @param typeId	accountType1：保证金账户；accountType2：账户余额
	 * @return
	 */
	public String getTradeAccountMoneyByCustomer(Long customerId, String typeId) {
		StringBuilder sql = new StringBuilder("select t.balance from tnb_account t where "
				+ "t.customer_id = " + customerId + " and t.del_status != 1 " + "  and t.type_id = "
				+ "(select id from t_s_type where typecode = '" + typeId + "' ) "); 
		List<Map<String, Object>> ls = getJdbcTemplate().queryForList(sql.toString());
		if (ls != null && ls.size() > 0) {
			return ls.get(0).get("balance") + "";
		}
		return "0";
	}
	
	/**
	 * 根据用户和账户类型获取账户
	 * @param customerId
	 * @param typeId	accountType1：保证金账户；accountType2：账户余额
	 * @return
	 */
	public TradeAccount getTradeAccountByCustomer(Long customerId, String typeId) {
		TradeAccount cb = (TradeAccount) this.em.createQuery("select t from TradeAccount t where t.customer.id = ?1 and t.type.typecode = ?2 and t.delStatus = 0 ")
				.setParameter(1,customerId).setParameter(2, typeId).getSingleResult();
		return cb;
	}

	// 获取账单
	public CustomerBill getCustomerBillById(CustomerBill bill) {
		CustomerBill cb = (CustomerBill) this.em.createQuery("select c from CustomerBill c where c.id = ?1")
				.setParameter(1, bill.getId()).getSingleResult();
		return cb;
	}
	
	// 获取结算账单
	public SettlementBill getSettlementBillById(SettlementBill bill) {
		SettlementBill cb = (SettlementBill) this.em.createQuery("select c from SettlementBill c where c.id = ?1")
				.setParameter(1, bill.getId()).getSingleResult();
		return cb;
	}

	// 更新账户余额
	@Transactional
	public Double updateAccountBalance(TradeAccount account, Double money) {
		TradeAccount payerAccount = (TradeAccount) this.em.createQuery("select a from TradeAccount a where a.id = ?1 ")
				.setParameter(1, account.getId()).getSingleResult();
		account.setBalance(payerAccount.getBalance() + money);
		dslJpaService.setEntityClass(TradeAccount.class);
		dslJpaService.update(account);
		return account.getBalance();
	}

	
	/**
	 * 账单审核通过生成流水记录 更改电子账户金额
	 * 
	 * @author huibati
	 * @param 2017年12月11日
	 */
	@Transactional
	public void updateEAccountBalanceByBill(Customer customer, CustomerBill bill) {
		List<TradeAccount> acountList = new ArrayList<>();
		acountList = this.em.createQuery("select a from TradeAccount a where a.customer.id = ?1 and a.delStatus != ?2 ")
				.setParameter(1, customer.getId()).setParameter(2, (short) 1).getResultList();
		// 获取客户两个账户
		TradeAccount cuEAccount = null;
		TradeAccount cuEnsureAccount = null;
		for (TradeAccount account : acountList) {
			if (account != null) {
				if (CommonConstants.DICTTYPE.ACCOUNT_TYPE_2.label().equals(account.getType().getTypecode())) {
					cuEAccount = account;
				} else {
					cuEnsureAccount = account;
				}
			}
		}
		//获取机构账户
		TradeAccount orgAccount = (TradeAccount) this.em
				.createQuery("select a from TradeAccount a where a.org.id = ?1 and a.delStatus != ?2 ")
				.setParameter(1, ActionContextHolder.getContext().getUser().getOrg().getId()).setParameter(2, (short) 1)
				.getSingleResult();
		// 生成扣款流水
		TradeDetail detailE = new TradeDetail();
		detailE.setMoney(bill.getTotal());
		detailE.setGatherAccount(orgAccount);
		detailE.setPayAccount(cuEAccount);
		detailE.setBalance(cuEAccount.getBalance() - bill.getTotal());
		detailE.setEnSurebalance(cuEnsureAccount.getBalance());
		detailE.setRemark(bill.getRemark());
		// 设置账户余额
		cuEAccount.setBalance(cuEAccount.getBalance() - bill.getTotal());
		orgAccount.setBalance(orgAccount.getBalance() + bill.getTotal());
		dslJpaService.setEntityClass(TradeAccount.class);
		dslJpaService.update(orgAccount);// 更新机构账户余额
		dslJpaService.update(cuEAccount);// 更新电子账户余额
		dslJpaService.setEntityClass(TradeDetail.class);
		if (customer.getChargeType() == null) {
			detailE.setType(commonService.getDicttype("consumeType1"));
		} else {
			if (CommonConstants.DICTTYPE.CHARGE_TYPE_D.label().equals(customer.getChargeType().getTypecode())) {
				detailE.setType(commonService.getDicttype("consumeType2"));
			}
			if (CommonConstants.DICTTYPE.CHARGE_TYPE_Y.label().equals(customer.getChargeType().getTypecode())) {
				detailE.setType(commonService.getDicttype("consumeType1"));
			}
		}
		dslJpaService.create(detailE);// 电子账户流水
		// bill账单类型为日结算 同时将所属日账单改为已结算
		if (bill.getBillType() != null
				&& CommonConstants.DICTTYPE.CHARGE_TYPE_D.label().equals(bill.getBillType().getTypecode())) {
			// 处理增值服务账单
			if (bill.getBillStatType() != null && "billStatTypeZZ".equals(bill.getBillStatType().getTypecode())) {
				String queryServiceBill = "update CustomerServiceBill u set u.billStatus = ?1 , u.lastUpdateDateTime = ?2 where u.bill.id = ?3";
				this.em.createQuery(queryServiceBill)
						.setParameter(1,
								commonService.getDicttype(CommonConstants.DICTTYPE.DAY_BILL_STATUS_YJS.label()))// 已结算
						.setParameter(2, CommonUtil.getCurrTimes()).setParameter(3, bill.getId()).executeUpdate();
			}
			// 处理基础服务账单
			if (bill.getBillStatType() != null && "billStatTypeJC".equals(bill.getBillStatType().getTypecode())) {
				String queryDayBill = "update CustomerDayBill u set u.billStatus = ?1 , u.lastUpdateDateTime = ?2 where u.bill.id = ?3";
				this.em.createQuery(queryDayBill)
						.setParameter(1,
								commonService.getDicttype(CommonConstants.DICTTYPE.DAY_BILL_STATUS_YJS.label()))// 已结算
						.setParameter(2, CommonUtil.getCurrTimes()).setParameter(3, bill.getId()).executeUpdate();
			}
		}
		dslJpaService.setEntityClass(CustomerBill.class);
		
		// 查看是否有退住结算单，如果有则更新
		checkAndUpdateSettlementBill(customer);
	}
	
	/**
	 * 查找退住结算单，如果存在，则更新退住结算单中的费用
	 */
	public void checkAndUpdateSettlementBill(Customer customer) {
		List<SettlementBill> billList =new ArrayList<>();
		billList = this.em.createQuery("select a from SettlementBill a where a.customer.id = ?1 and a.delStatus != ?2 ")
				.setParameter(1, customer.getId()).setParameter(2, (short)1).getResultList();
		if (billList.size() > 0) {
			SettlementBill bill = billList.get(0);
			bill.setAccountAmount(getTradeAccountByCustomer(customer.getId(), "accountType2").getBalance());	// 余额
			bill.setDepositAmount(getTradeAccountByCustomer(customer.getId(), "accountType1").getBalance());	// 保证金
			
			bill.setTotalAmount(bill.getAccountAmount() + bill.getDepositAmount());
			Dicttype typeDict = null;
			bill.setTotalAmount(bill.getAccountAmount() + bill.getDepositAmount());
			if (bill.getTotalAmount() > 0) {
				typeDict = commonService.getDicttype(CommonConstants.SETTLEMENT_TYPE.REFUND.lable());// 账单类型：退费
			} else {
				typeDict = commonService.getDicttype(CommonConstants.SETTLEMENT_TYPE.DEDUCT.lable());// 账单类型：缴费
				bill.setTotalAmount(-bill.getTotalAmount());	// 根据类型区别，总金额取绝对值
			}
			bill.setBillType(typeDict);
			bill.setLastUpdateDateTime(CommonUtil.getCurrTimes());
			dslJpaService.setEntityClass(SettlementBill.class);
			dslJpaService.update(bill);
		}
	}
	
	/**
	 * 查找是否有审核未通过的账单
	 * @param customer
	 * @return
	 */
	public boolean checkBillFinish(Customer customer) {
		List<CustomerBill> billList =new ArrayList<>();
		billList = this.em.createQuery("select a from CustomerBill a where a.customer.id = ?1 and a.delStatus != ?2 and a.billStatus.typecode != ?3 ")
				.setParameter(1, customer.getId()).setParameter(2, (short)1).setParameter(3, CommonConstants.DICTTYPE.BILL_STATUS_2.label()).getResultList();
		if (billList.size() > 0) {
			return false;
		}
		return true;
	}
	
	// 账单审核通过生成流水记录 更改账户金额
	@Transactional
	public void updateAccountBalanceByBill(Customer customer, CustomerBill bill) {
		int flag = 0;
		int flag0 = 0;//电子钱包流水生成标识
		List<TradeAccount> acountList =new ArrayList<>();
		acountList = this.em.createQuery("select a from TradeAccount a where a.customer.id = ?1 and a.delStatus != ?2 ")
				.setParameter(1, customer.getId()).setParameter(2, (short)1).getResultList();
		TradeAccount cuEAccount = null;
		TradeAccount cuEnsureAccount = null;
		for (TradeAccount account : acountList) {
			if (account != null) {
				if (CommonConstants.DICTTYPE.ACCOUNT_TYPE_2.label().equals(account.getType().getTypecode())) {
					cuEAccount = account;
				} else {
					cuEnsureAccount = account;
				}
			}
		}
		TradeAccount orgAccount = (TradeAccount) this.em.createQuery("select a from TradeAccount a where a.org.id = ?1 and a.delStatus != ?2 ")
				.setParameter(1, ActionContextHolder.getContext().getUser().getOrg().getId()).setParameter(2, (short)1).getSingleResult();
		TradeDetail detailE = new TradeDetail(); 
		TradeDetail detailEnsure = null;
		if (cuEAccount.getBalance() >= bill.getTotal()) {
			// 生成扣款流水
			flag0 = 1;
			detailE.setMoney(bill.getTotal());
			detailE.setGatherAccount(orgAccount);
			detailE.setPayAccount(cuEAccount);
			detailE.setBalance(cuEAccount.getBalance() - bill.getTotal());
			detailE.setEnSurebalance(cuEnsureAccount.getBalance());
			detailE.setRemark(bill.getRemark());
			// 设置账户余额
			cuEAccount.setBalance(cuEAccount.getBalance() - bill.getTotal());
		} else {
			flag = 1;
			// 生成电子钱包扣款流水
			if(cuEAccount.getBalance()<=0.0){
				//账户余额为零 不生成账户流水记录
			}else{
				flag0 = 1;
				detailE.setMoney(cuEAccount.getBalance());
				detailE.setGatherAccount(orgAccount);
				detailE.setPayAccount(cuEAccount);
				detailE.setRemark(bill.getRemark());
				detailE.setBalance(0.0);
				detailE.setEnSurebalance(cuEAccount.getBalance() - bill.getTotal() + cuEnsureAccount.getBalance());
			}
			//保证金账户流水
			detailEnsure = new TradeDetail();
			detailEnsure.setMoney(bill.getTotal() - cuEAccount.getBalance());
			detailEnsure.setGatherAccount(orgAccount);
			detailEnsure.setPayAccount(cuEnsureAccount);
			detailEnsure.setBalance(0.0);
			detailEnsure.setRemark(bill.getRemark());
			detailEnsure.setEnSurebalance(cuEAccount.getBalance() - bill.getTotal() + cuEnsureAccount.getBalance());
			// 设置账户余额
			cuEnsureAccount.setBalance(cuEAccount.getBalance() - bill.getTotal() + cuEnsureAccount.getBalance());
			cuEAccount.setBalance(0.0);
		}

		orgAccount.setBalance(orgAccount.getBalance() + bill.getTotal());
		dslJpaService.setEntityClass(TradeAccount.class);
		dslJpaService.update(orgAccount);// 更新机构账户余额
		dslJpaService.update(cuEAccount);// 更新电子账户余额
		if (flag == 1) {
			dslJpaService.update(cuEnsureAccount);// 更新保证金账户
		}

		dslJpaService.setEntityClass(TradeDetail.class);
		if (flag0 == 1) {
			if (customer.getChargeType() == null) {
				detailE.setType(commonService.getDicttype("consumeType1"));
			} else {
	            if (CommonConstants.DICTTYPE.CHARGE_TYPE_D.label().equals(customer.getChargeType().getTypecode())) {
					detailE.setType(commonService.getDicttype("consumeType2"));
				} 
	            if (CommonConstants.DICTTYPE.CHARGE_TYPE_Y.label().equals(customer.getChargeType().getTypecode())) {
					detailE.setType(commonService.getDicttype("consumeType1"));
				}
			}
		    dslJpaService.create(detailE);// 电子账户流水
		}
		if (flag == 1) {
			if (customer.getChargeType() == null) {
				detailEnsure.setType(commonService.getDicttype("consumeType1"));
			} else{
	            if (CommonConstants.DICTTYPE.CHARGE_TYPE_D.label().equals(customer.getChargeType().getTypecode())) {
					detailEnsure.setType(commonService.getDicttype("consumeType2"));
				} 
	            if (CommonConstants.DICTTYPE.CHARGE_TYPE_Y.label().equals(customer.getChargeType().getTypecode())) {
					detailEnsure.setType(commonService.getDicttype("consumeType1"));
				}
			}
			dslJpaService.create(detailEnsure);// 保证金账户流水
		}
//		if(bill.getFlow()!=null){//将退住flow改为费用结算完成
//			dslJpaService.setEntityClass(CustomerBusinessFlow.class);
//			bill.getFlow().setLeaveStatus(commonService.getDicttype(CommonConstants.DICTTYPE.FLOW_LEAVE_STATUS_6.label()));
//			dslJpaService.update(bill.getFlow());
//		}
		//bill账单类型为日结算 同时将所属日账单改为已结算
		if (bill.getBillType() != null
				&& CommonConstants.DICTTYPE.CHARGE_TYPE_D.label().equals(bill.getBillType().getTypecode())) {
			//处理增值服务账单
			if (bill.getBillStatType() != null && "billStatTypeZZ".equals(bill.getBillStatType().getTypecode())) {
				String queryServiceBill = "update CustomerServiceBill u set u.billStatus = ?1 , u.lastUpdateDateTime = ?2 where u.bill.id = ?3";
				this.em.createQuery(queryServiceBill)
						.setParameter(1,
								commonService.getDicttype(CommonConstants.DICTTYPE.DAY_BILL_STATUS_YJS.label()))// 已结算
						.setParameter(2, CommonUtil.getCurrTimes()).setParameter(3, bill.getId()).executeUpdate();
			}
			//处理基础服务账单
			if (bill.getBillStatType() != null && "billStatTypeJC".equals(bill.getBillStatType().getTypecode())) {
				String queryDayBill = "update CustomerDayBill u set u.billStatus = ?1 , u.lastUpdateDateTime = ?2 where u.bill.id = ?3";
				this.em.createQuery(queryDayBill)
						.setParameter(1,
								commonService.getDicttype(CommonConstants.DICTTYPE.DAY_BILL_STATUS_YJS.label()))// 已结算
						.setParameter(2, CommonUtil.getCurrTimes()).setParameter(3, bill.getId()).executeUpdate();
			}
		}
		dslJpaService.setEntityClass(CustomerBill.class);
	}

	
	/**
	 *   @author huibati
	 *   生成日期当天的日账单
	 *   2017年7月19日 
	 */
	public void createDayBill(Customer customer, String dayTime,Map<Customer, NursingLevel> projectMap) {
		logger.info("start create day bill " + CommonUtil.getCurrTimeForString() + " customerid " + customer.getId());
		String year = dayTime.substring(0, 4);
		String month = dayTime.substring(5, 7);
		String bedPrice = "0.0";
		String foodPrice = "0.0";
		String projectPrice = "0.0";
		String customerChargeType = customer.getChargeType() == null ? null : customer.getChargeType().getTypecode();// 月计费/日计费
		//建立日账单
		customer.setLeaveStatus(this.customerLeaveService.getLeaveStatus(customer));//获取老人请假状态
		CustomerDayBill dayBill = new CustomerDayBill();
		dayBill.setCustomer(customer);
		dayBill.setBillYear(Integer.parseInt(year));
		dayBill.setBillMonth(Integer.parseInt(month));
		dayBill.setTenant(customer.getTenant());//设置日账单时间属性
		try {
			dayBill.setBillTime(CommonUtil.strToIntegerTime(dayTime));
		} catch (Exception e) {
			logger.debug("createDayBill error " + e);
		}
		Integer dateStartTime = CommonUtil.getDayBegin(dayBill.getBillTime());
		Integer dateEndTime = CommonUtil.getDayEnd(new Date(dayBill.getBillTime().longValue() * 1000));
		List<CustomerDayBill> dayBillList = this.em
				.createQuery(
						"select a from CustomerDayBill a where a.delStatus != 1 and a.customer.id = ?1 and a.billYear =?2  and a.billMonth =?3 and "
						+ "(a.billTime >?4 and a.billTime < ?5) ")
				.setParameter(1, customer.getId())
				.setParameter(2, Integer.parseInt(year)).setParameter(3, dayBill.getBillMonth())
				.setParameter(4, dateStartTime).setParameter(5, dateEndTime).getResultList();
		CustomerDayBill billTemp=dayBillList==null||dayBillList.size()==0?null:dayBillList.get(0);
		if (billTemp != null) {
			logger.info("end create day bill already in" + dayBill.getBillTime() + " customerid " + customer.getId());
			return;
		}
		
		// 如果当天有服务变更记录，则标识
		StringBuilder query = new StringBuilder("select c from CustomerServerChange c where c.customer.id = ?1 and c.effectiveTime >= ?2 and "
				+ "c.effectiveTime <= ?3 ");// user对应Employee
		Integer startTime = CommonUtil.getDayBegin();
		Integer endTime = startTime + 3600 * 24;
		List<Employee> employeeList = this.em.createQuery(query.toString()).setParameter(1, customer.getId())
				.setParameter(2, startTime).setParameter(3, endTime).getResultList();
		if (!employeeList.isEmpty()) {
			dayBill.setIsServiceChanged("1");
		} else {
			dayBill.setIsServiceChanged("0");
		}
		
		//获取床位餐饮护理参考费用
		if (customer.getActualBedPrice() != null) {
			bedPrice = customer.getActualBedPrice().toString();
		}
		dayBill.setTotal1(Double.parseDouble(bedPrice));// 床位
		if (customer.getActualDiningPrice() != null) {
			foodPrice = customer.getActualDiningPrice().toString();
		}
		dayBill.setTotal2(Double.parseDouble(foodPrice));// canyin
		NursingProject project = nursingService.getProjectByCustomer(customer);
		if (project != null && project.getPrice() != null) {
			projectPrice = project.getPrice().toString();
		}
		/*if (customer.getActualNursingPrice() != null) {
			projectPrice = customer.getActualNursingPrice();
		}*/
		dayBill.setTotal3(Double.valueOf(projectPrice));// project
		
		//判断老人收费类型
		if (customerChargeType != null && CommonConstants.DICTTYPE.CHARGE_TYPE_Y.label().equals(customerChargeType)) {
			//平均值
//			int days=CommonUtil.getDays(Integer.parseInt(year),Integer.parseInt(month));
			BigDecimal b = new BigDecimal(customer.getActualPrice()).multiply(new BigDecimal(12)).divide(new BigDecimal("365"), 2, BigDecimal.ROUND_HALF_UP);
			//Double dayPrice=customer.getTotalPrice()/(days*1.0);//  月费用/月天数
//			Double dayPrice=Double.parseDouble(customer.getActualPrice())/(days*1.0);//  月费用/月天数
//			Double dayPrice= totalYearPrice.doubleValue();//  月费用/月天数
//			BigDecimal b = new BigDecimal(dayPrice);
			Double dayPrice = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
			dayBill.setTotal(dayPrice);
			
//			b=new BigDecimal(Double.parseDouble(bedPrice)/(days*1.0));// 床位  月费用/月天数
			b = new BigDecimal(bedPrice).multiply(new BigDecimal(12)).divide(new BigDecimal("365"), 2, BigDecimal.ROUND_HALF_UP);
			dayBill.setTotal1(b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());// 床位
			
			b = new BigDecimal(foodPrice).multiply(new BigDecimal(12)).divide(new BigDecimal("365"), 2, BigDecimal.ROUND_HALF_UP);
//			b=new BigDecimal(Double.parseDouble(foodPrice)/(days*1.0));// 床位  月费用/月天数
			dayBill.setTotal2(b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());// canyin
			
			b = new BigDecimal(projectPrice).multiply(new BigDecimal(12)).divide(new BigDecimal("365"), 2, BigDecimal.ROUND_HALF_UP);
//			b=new BigDecimal(Double.parseDouble(projectPrice)/(days*1.0));// 床位  月费用/月天数
			dayBill.setTotal3(b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());// project
			
			dayBill.setDayBillType(commonService.getDicttype(CommonConstants.DICTTYPE.CHARGE_TYPE_Y.label()));
			dayBill.setRemark("月费:"+customer.getActualPrice()+"元");
		}
		if (customerChargeType == null || CommonConstants.DICTTYPE.CHARGE_TYPE_D.label().equals(customerChargeType)) {
			if (customer.getActualPrice() != null && !"".equals(customer.getActualPrice())) { // 老人实际住宿价格不为空
				dayBill.setTotal(Double.parseDouble(customer.getActualPrice()));
				dayBill.setTotal1(Double.parseDouble(bedPrice));// 床位
				dayBill.setTotal2(Double.parseDouble(foodPrice));// canyin
				dayBill.setTotal3(Double.valueOf(projectPrice));// project
				if(customerChargeType != null ){
					dayBill.setDayBillType(commonService.getDicttype(CommonConstants.DICTTYPE.CHARGE_TYPE_D.label()));//日结
					dayBill.setBillStatus(commonService.getDicttype(CommonConstants.DICTTYPE.DAY_BILL_STATUS_WJS.label()));//未结算
				}
				dayBill.setRemark("日费:"+customer.getActualBedPrice()+"元");
			}
		}
		dayBill.setDiningStandard(customer.getDiningStandard());
		if (projectMap != null) {
			for (Customer older : projectMap.keySet()) {
				if (older.getId().longValue() == customer.getId().longValue()) {
					dayBill.setLevel(projectMap.get(older));
					break;
				}
			}
		}
		if (customer.getLeaveStatus() == null || customer.getLeaveStatus() == CommonConstants.DEFAULT_STATUS_NO_0) {
			dayBill.setCustomerStatus(customer.getCustomerStatus());
		}
		if (customer.getLeaveStatus() != null && customer.getLeaveStatus() == CommonConstants.DEFAULT_STATUS_YES_1) {
			dayBill.setCustomerStatus(commonService.getDicttype(CommonConstants.DICTTYPE.CUSTOMER_LEAVING.label()));//请假
		}
		dayBill.setCreateDateTime(CommonUtil.getCurrTimes());
		dslJpaService.setEntityClass(CustomerDayBill.class);
		dslJpaService.create(dayBill);
		logger.info("end create day bill " + CommonUtil.getCurrTimeForString() + " customerid " + customer.getId());
	}

	// 生成账单
	@Transactional
	public void createCustomerBill(Customer Customer, Dicttype billType) {
		CustomerBill bill = new CustomerBill();
		dslJpaService.setEntityClass(CustomerBill.class);
		dslJpaService.create(bill);
	}

	/**
	 *   @author huibati
	 *   @param 
	 *         flow:bill所关联的flow
	 *         leaveMap:时间段内请假数据  changeMap：时间段内服务变更数据(用于判断bill是否可以直接审核通过)
	 *   统计时间段内的日账单生成总账单
	 *   2017年7月19日 
	 */
	public void createCustomerBill(Customer customer, Integer startTime, Integer endTime, CustomerBusinessFlow flow,
			Map<Customer, CustomerServerChange> changeMap, Map<Customer, CustomerLeave> leaveMap) {
		createCustomerBill(customer, startTime, endTime, flow, changeMap, leaveMap, CommonConstants.DICTTYPE.BILL_TYPE_2.label());
	}
	public void createCustomerBill(Customer customer, Integer startTime, Integer endTime, CustomerBusinessFlow flow,
			Map<Customer, CustomerServerChange> changeMap, Map<Customer, CustomerLeave> leaveMap, String billType) {
		logger.info("start create bill "+CommonUtil.getCurrTimeForString()+" customerid "+customer.getId());
		List<CustomerBill> dataList = new ArrayList<>();
		String date=CommonUtil.integetTimeForString(startTime);
		String customerChargeType = customer.getChargeType() == null ? null : customer.getChargeType().getTypecode();// 月计费/日计费
		//统计日账单
		Double total1 = 0.0;
		Double total2 = 0.0;
		Double total3 = 0.0;
		Double total = 0.0;
		int dayBillNum=0;//入住天数
		List<CustomerDayBill> dayBillList = new ArrayList<>();
		dayBillList = this.em
				.createQuery(
						"select a from CustomerDayBill a where a.delStatus != 1 and a.customer.id = ?1 and a.billTime >=?2 and a.billTime <?3 ")
				.setParameter(1, customer.getId()).setParameter(2, startTime).setParameter(3, endTime).getResultList();
		
		String remark = "";
		if(dayBillList!=null){
//			for (CustomerDayBill dayBill : dayBillList) {
			for (int i = 0; i < dayBillList.size(); i++) {
				CustomerDayBill dayBill = dayBillList.get(i);
				if (dayBill != null) {
					if (dayBill.getDayBillType().getTypecode().equals(CommonConstants.DICTTYPE.CHARGE_TYPE_D.label())) {	// 去除试住日统计的账单
						continue;
					}
					// #由于请假业务复杂，现在总金额不考虑请假的情况，只在备注里面记录
					total1 += dayBill.getTotal1();
					total2 += dayBill.getTotal2();
					total3 += dayBill.getTotal3();
					total += dayBill.getTotal();
					if (!dayBill.getCustomerStatus().getTypecode().equals(CommonConstants.DICTTYPE.CUSTOMER_LEAVING.label())) {	// 只计算在住的天数
						dayBillNum ++;
					} else {
						remark += CommonUtil.integetTimeForString(dayBill.getBillTime()).substring(8, 10).replace("-", "月") + "日" + ",";
					}
				}
			}
//			dayBillNum=dayBillList.size();
		}
		if (!"".equals(remark)) {
			remark = "本账单期间，" + customer.getName() + "老人在本月'" + remark.substring(0, remark.length() - 1) + "' 请假，请酌情扣减账单费用";
		}
		CustomerBill bill = new CustomerBill();
		//设置月账单类型
		bill.setBillMonth(Integer.parseInt(date.substring(5, 7)));
		bill.setBillYear(Integer.parseInt(date.substring(0, 4)));
		bill.setCustomer(customer);
		bill.setTenant(customer.getTenant());
		bill.setDelStatus((short)0);
		bill.setBillStatus(commonService.getDicttype(CommonConstants.DICTTYPE.BILL_STATUS_0.label()));// 未提交
		bill.setBillStatType(commonService.getDicttype("billStatTypeJC"));//基础服务统计
		bill.setBillType(commonService.getDicttype(CommonConstants.DICTTYPE.BILL_TYPE_2.label()));//月账单
		bill.setBillCreateType(commonService.getDicttype("createType1"));//系统生成
		bill.setBillTime(startTime);// 当月第一天时间
		bill.setCreateDateTime(CommonUtil.getCurrTimes());
		if (!"".equals(remark)) {
			bill.setRemark(remark);
		}
		if (customerChargeType == null || CommonConstants.DICTTYPE.CHARGE_TYPE_D.label().equals(customerChargeType)) {
			bill.setTotal(new BigDecimal(total).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue());
			bill.setTotal1(total1);
			bill.setTotal2(total2);
			bill.setTotal3(total3);
		}
		if (customerChargeType != null && CommonConstants.DICTTYPE.CHARGE_TYPE_Y.label().equals(customerChargeType)) {
			//String year = date.substring(0, 4);
			//String month = date.substring(5, 7);
			//int days = CommonUtil.getDays(Integer.parseInt(year), Integer.parseInt(month));
			//如果有请假或者服务变更账单金额为日账单金额之和     
			if (changeMap.containsKey(customer)) {
				bill.setOperateFlag("1");
			} else {
				// 无请假以及服务变更就按照入住天数比例收费
				bill.setOperateFlag("0");
				//total = dayBillNum * Double.parseDouble(customer.getActualPrice()) / (days * 1.0);
			}
//			BigDecimal b = new BigDecimal(total);
			//total = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
//			total = Double.parseDouble(customer.getActualPrice());//月统计账单总额 就为客户信息中每月实际价格 具体数额人工审核
			bill.setTotal(new BigDecimal(total).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue());
		}
		if (flow != null) {
			bill.setFlow(flow);
		}
		dataList.add(bill);
		//统计增值服务账单
		List<CustomerServiceBill> serviceBillList = new ArrayList<>();
		serviceBillList = this.em
				.createQuery(
						"select a from CustomerServiceBill a where a.delStatus != 1 and a.customer.id = ?1 and a.billTime >=?2 and a.billTime <?3 ")
				.setParameter(1, customer.getId()).setParameter(2, startTime).setParameter(3, endTime).getResultList();
		Double ZZTotal = 0.0;
		for (CustomerServiceBill serviceBill : serviceBillList) {
			if (serviceBill != null) {
				ZZTotal += serviceBill.getTotal();
			}
		}
		CustomerBill serviceBill = new CustomerBill();
		//设置月账单类型
		serviceBill.setBillMonth(Integer.parseInt(date.substring(5, 7)));
		serviceBill.setBillYear(Integer.parseInt(date.substring(0, 4)));
		serviceBill.setCustomer(customer);
		serviceBill.setTenant(customer.getTenant());
		serviceBill.setTotal(new BigDecimal(ZZTotal).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue());
		serviceBill.setDelStatus((short) 0);
		serviceBill.setBillStatus(commonService.getDicttype(CommonConstants.DICTTYPE.BILL_STATUS_0.label()));// 未提交
		serviceBill.setBillStatType(commonService.getDicttype("billStatTypeZZ"));//增值服务统计
		serviceBill.setBillTime(startTime);// 当月第一天时间 
		
		serviceBill.setBillType(commonService.getDicttype(billType));// 根据传入类型确定 账单类型，年/月/周/日等
		
		serviceBill.setBillCreateType(commonService.getDicttype("createType1"));//系统生成
		serviceBill.setCreateDateTime(CommonUtil.getCurrTimes());
		dataList.add(serviceBill);
		//批量增添
		commonService.batchInsert(dataList);
		logger.info("end create bill "+CommonUtil.getCurrTimeForString());
	}
	
	/**
	 *   
	 *   @author huibati
	 *   @param
	 *   2017年10月12日
	 */
	public void createRechargeRecord(RechargeRecord record){
		dslJpaService.setEntityClass(RechargeRecord.class);
		dslJpaService.create(record);
	}
	
	public TradeAccount findOrgAccountByOrg(Long orgId) {
		TradeAccount orgAccount = null;
		orgAccount = (TradeAccount) this.em.createQuery("select a from TradeAccount a where a.org.id = ?1 and a.delStatus!=?2 ")
				.setParameter(1, orgId).setParameter(2, (short)1).getSingleResult();
		return orgAccount;
	}
	
	/**
	 * 统计相应老人未结算的日账单 并生成相应总账单
	 * 
	 * @author huibati
	 * @param 2017年10月11日
	 */
	@Transactional
	public CustomerBill operateCustomerDayBill(CustomerBill bill, Customer customer,CustomerBusinessFlow flow) {
		// 总账单金额
		Double total1 = 0.0;
		Double total2 = 0.0;
		Double total3 = 0.0;
		Double total = 0.0;
		int year = 0;
		int month = 0;
		int startTime = 0;
		int endTime = 0;
		if ("billStatTypeJC".equals(bill.getBillStatType().getTypecode())) {
			// 未结算基础服务日账单
			List<CustomerDayBill> dayBillList = this.em
					.createQuery(
							"select a from CustomerDayBill a where a.delStatus != 1 and a.customer.id = ?1 and a.billStatus.typecode =?2  and a.bill is null  order by billTime  asc")
					.setParameter(1, customer.getId())
					.setParameter(2, CommonConstants.DICTTYPE.DAY_BILL_STATUS_WJS.label()).getResultList();
			if (dayBillList != null && dayBillList.size() > 0) {
				bill.setDelStatus((short) 1);
				bill.setCustomer(customer);
				bill.setTenant(customer.getTenant());
				bill.setBillStatType(commonService.getDicttype("billStatTypeJC"));// 基础服务统计
				dslJpaService.setEntityClass(CustomerBill.class);
				dslJpaService.create(bill);
				startTime = dayBillList.get(0).getBillTime();
				endTime = dayBillList.get(dayBillList.size()-1).getBillTime();
				year = dayBillList.get(0).getBillYear();
				month = dayBillList.get(0).getBillMonth();
				for (CustomerDayBill dayBill : dayBillList) {
					if (dayBill != null) {
						total1 += dayBill.getTotal1();
						total2 += dayBill.getTotal2();
						total3 += dayBill.getTotal3();
						total += dayBill.getTotal();
						dayBill.setBill(bill);
					}
				}
				// 更新日账单数据
				commonService.batchUpdate(dayBillList);
			} else {
				bill.setErrcode(0);// 无未结算账单
				return bill;
			}
		}
		if ("billStatTypeZZ".equals(bill.getBillStatType().getTypecode())) {
			// 未结算增值服务日账单
			List<CustomerServiceBill> serviceBillList = this.em
					.createQuery(
							"select a from CustomerServiceBill a where a.delStatus != 1 and a.customer.id = ?1 and a.billStatus.typecode =?2  and a.bill is null order by billTime  asc")
					.setParameter(1, customer.getId())
					.setParameter(2, CommonConstants.DICTTYPE.DAY_BILL_STATUS_WJS.label()).getResultList();
			if (serviceBillList != null && serviceBillList.size() > 0) {
				bill.setDelStatus((short) 1);
				bill.setCustomer(customer);
				bill.setTenant(customer.getTenant());
				bill.setBillStatType(commonService.getDicttype("billStatTypeZZ"));// 基础服务统计
				dslJpaService.setEntityClass(CustomerBill.class);
				dslJpaService.create(bill);
				startTime = serviceBillList.get(0).getBillTime();
				year = serviceBillList.get(0).getBillYear();
				month = serviceBillList.get(0).getBillMonth();
				for (CustomerServiceBill serviceBill : serviceBillList) {
					if (serviceBill != null) {
						total += serviceBill.getTotal();
						serviceBill.setBill(bill);
					}
				}
				// 更新日账单数据
				commonService.batchUpdate(serviceBillList);
			} else {
				bill.setErrcode(0);// 无未结算账单
				return bill;
			}
		}
		// 设置总账单数据
		bill.setBillMonth(month);
		bill.setBillYear(year);
		bill.setDelStatus((short) 0);
		//bill.setBillStatus(commonService.getDicttype(CommonConstants.DICTTYPE.BILL_STATUS_0.label()));// 未提交
		bill.setBillType(commonService.getDicttype(CommonConstants.DICTTYPE.CHARGE_TYPE_D.label()));// 日结算
		bill.setBillCreateType(commonService.getDicttype("createType1"));// 系统生成
		bill.setBillTime(startTime);// 账单第一天时间
		bill.setBillQuarter(endTime);//账单最后一天时间
		if (bill.getTotal() == null) {
			bill.setTotal(total);
		}
		bill.setTotal1(total1);
		bill.setTotal2(total2);
		bill.setTotal3(total3);
		if(flow!=null){
			bill.setFlow(flow);
		}
		dslJpaService.setEntityClass(CustomerBill.class);
		dslJpaService.update(bill);
		return bill;
	}
	
	/**
	 * 生成交易记录并修改账户金额
	 * 
	 * @author huibati
	 * @param 2017年10月12日
	 */
	@Transactional
	public RechargeRecord updateRechargeRecord(RechargeRecord record, TradeAccount customerAccount, TradeAccount orgAccount) {
		Double recharge = record.getMoney();
		Double customerBalance = this.updateAccountBalance(customerAccount, recharge);// 修改老人账户
		//this.updateAccountBalance(orgAccount, recharge);// 修改机构账户
		record.setBalance(customerBalance);
		record.setCreateDateTime(CommonUtil.getCurrTimes());
		dslJpaService.setEntityClass(RechargeRecord.class);
		dslJpaService.update(record);
		return record;
	}

	
	
	/**
	 * 删除customerbill
	 * 
	 * @author huibati
	 * @param 2017年10月11日
	 */
	@Transactional
	public CustomerBill deleteCustomerDayBill(CustomerBill bill) {
		String queryDayBill = "update CustomerDayBill u set u.bill = null , u.lastUpdateDateTime = ?2 where u.bill.id = ?3";
		this.em.createQuery(queryDayBill)
				.setParameter(2, CommonUtil.getCurrTimes()).setParameter(3, bill.getId()).executeUpdate();
		bill.setDelStatus((short)1);
		dslJpaService.setEntityClass(CustomerBill.class);
		dslJpaService.update(bill);
		return bill;
	}
	
	/**
	 * 获取与业务表关联的账单信息
	 *   @author huibati
	 *   @param
	 *   2017年10月30日
	 */
	public List<CustomerBill> findCustomerBillOnFlow(List<CustomerBusinessFlow> flows) {
		List<CustomerBill> bills = null;
		if (flows != null && flows.size()>0) {
			bills = this.em.createQuery("select a from CustomerBill a where a.flow is not null and a.flow in (:flows) and a.delStatus != ?1 ")
					.setParameter("flows", flows).setParameter(1, (short) 1).getResultList();
		}
		return bills;
	}
	
	/**
	 * 清除用户账户金额
	 * @param customer
	 */
	public void clearCustomerAccount(Customer customer) {
		if (!checkBillFinish(customer)) {
			throw new BusinessException(null, CommonConstants.ERROR_CODE.ADD_ERROR.label(), null);
		}
		TradeAccount accMoney = getTradeAccountByCustomer(customer.getId(), "accountType2");	// 余额
		TradeAccount depoMoney = getTradeAccountByCustomer(customer.getId(), "accountType1");	// 保证金
		updateAccountBalance(accMoney, 0.00);
		updateAccountBalance(depoMoney, 0.00);
		customer.setAccountMoney("0");
		customer.setActualDeposit("0");
		dslJpaService.setEntityClass(Customer.class);
		dslJpaService.update(customer);
	}
}
